Micron Document
🎖️GitЯра🎖️

Node / meshtastic / Meshtastic-Android / files / app / src / main / java / com / geeksville / mesh / service / PacketHandler.kt

Displaying Raw • Download

app/src/main/java/com/geeksville/mesh/service/PacketHandler.kt ui_message_list (be3f882f) Text, 7.88 KB

T8b949e/*
* Copyright (c) 2025 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

Tff7b72package T7ee787com.geeksville.mesh.service

Tff7b72import T7ee787com.geeksville.mesh.DataPacket
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos.MeshPacket
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos.ToRadio
Tff7b72import T7ee787com.geeksville.mesh.MessageStatus
Tff7b72import T7ee787com.geeksville.mesh.android.BuildUtils.debug
Tff7b72import T7ee787com.geeksville.mesh.android.BuildUtils.errormsg
Tff7b72import T7ee787com.geeksville.mesh.android.BuildUtils.info
Tff7b72import T7ee787com.geeksville.mesh.concurrent.handledLaunch
Tff7b72import T7ee787com.geeksville.mesh.database.MeshLogRepository
Tff7b72import T7ee787com.geeksville.mesh.database.PacketRepository
Tff7b72import T7ee787com.geeksville.mesh.database.entity.MeshLog
Tff7b72import T7ee787com.geeksville.mesh.fromRadio
Tff7b72import T7ee787com.geeksville.mesh.repository.radio.RadioInterfaceService
Tff7b72import T7ee787com.geeksville.mesh.util.toOneLineString
Tff7b72import T7ee787com.geeksville.mesh.util.toPIIString
Tff7b72import T7ee787dagger.Lazy
Tff7b72import T7ee787java8.util.concurrent.CompletableFuture
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.Dispatchers
Tff7b72import T7ee787kotlinx.coroutines.Job
Tff7b72import T7ee787kotlinx.coroutines.delay
Tff7b72import T7ee787kotlinx.coroutines.withTimeoutOrNull
Tff7b72import T7ee787java.util.UUID
Tff7b72import T7ee787java.util.concurrent.ConcurrentLinkedQueue
Tff7b72import T7ee787java.util.concurrent.TimeUnit
Tff7b72import T7ee787java.util.concurrent.TimeoutException

Tff7b72class T56d364PacketHandlerTb4b4b4(
Tff7b72private Tff7b72val Te6edf3packetRepositoryTb4b4b4: Te6edf3LazyTff7b72<Te6edf3PacketRepositoryTff7b72>Tb4b4b4,
Tff7b72private Tff7b72val Te6edf3serviceBroadcastsTb4b4b4: Te6edf3MeshServiceBroadcastsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioInterfaceServiceTb4b4b4: Te6edf3RadioInterfaceServiceTb4b4b4,
Tff7b72private Tff7b72val Te6edf3meshLogRepositoryTb4b4b4: Te6edf3LazyTff7b72<Te6edf3MeshLogRepositoryTff7b72>Tb4b4b4,
Tb4b4b4) Tb4b4b4{

Tff7b72private Tff7b72var Te6edf3queueJobTb4b4b4: Te6edf3Job? Tff7b72= Tff7b72null
Tff7b72private Tff7b72val Te6edf3scope Tff7b72= Te6edf3CoroutineScopeTb4b4b4(Te6edf3DispatchersTb4b4b4.Te6edf3IOTb4b4b4)

Tff7b72private Tff7b72val Te6edf3queuedPackets Tff7b72= Te6edf3ConcurrentLinkedQueueTff7b72<Te6edf3MeshPacketTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3queueResponse Tff7b72= Te6edf3mutableMapOfTff7b72<Tffa657IntTb4b4b4, Te6edf3CompletableFutureTff7b72<Tffa657BooleanTff7b72>Tff7b72>Tb4b4b4(Tb4b4b4)

T8b949e/**
* Send a command/packet to our radio. But cope with the possibility that we might start up before we are fully
* bound to the RadioInterfaceService
*/
Tff7b72fun Td2a8ffsendToRadioTb4b4b4(Te6edf3pTb4b4b4: Te6edf3ToRadioTb4b4b4.Te6edf3BuilderTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3built Tff7b72= Te6edf3pTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffSending to radio Tffd700${Te6edf3builtTb4b4b4.Te6edf3toPIIStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3b Tff7b72= Te6edf3builtTb4b4b4.Te6edf3toByteArrayTb4b4b4(Tb4b4b4)

Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3bTb4b4b4)
Te6edf3changeStatusTb4b4b4(Te6edf3pTb4b4b4.Te6edf3packetTb4b4b4.Te6edf3idTb4b4b4, Te6edf3MessageStatusTb4b4b4.Te6edf3ENROUTETb4b4b4)

Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3packetTb4b4b4.Te6edf3hasDecodedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffPacketTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3pTb4b4b4.Te6edf3packetTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromNum Tff7b72= Te6edf3pTb4b4b4.Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4,
Te6edf3portNum Tff7b72= Te6edf3pTb4b4b4.Te6edf3packetTb4b4b4.Te6edf3decodedTb4b4b4.Te6edf3portnumValueTb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Te6edf3packet Tff7b72= Te6edf3pTb4b4b4.Te6edf3packet Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
Tb4b4b4}

T8b949e/**
* Send a mesh packet to the radio, if the radio is not currently connected this function will throw
* NotConnectedException
*/
Tff7b72fun Td2a8ffsendToRadioTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4, Te6edf3getConnectionStateTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Te6edf3ConnectionStateTb4b4b4) Tb4b4b4{
Te6edf3queuedPacketsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3packetTb4b4b4)
Te6edf3startPacketQueueTb4b4b4(Te6edf3getConnectionStateTb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffstopPacketQueueTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3queueJobTff7b72?.Te6edf3isActive Tff7b72=Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffStopping packet queueJobTa5d6ff"Tb4b4b4)
Te6edf3queueJobTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3queueJob Tff7b72= Tff7b72null
Te6edf3queuedPacketsTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Te6edf3queueResponseTb4b4b4.Te6edf3entriesTb4b4b4.Te6edf3lastOrNull Tb4b4b4{ Tff7b72!Tffa657itTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3isDone Tb4b4b4}Tff7b72?.Te6edf3valueTff7b72?.Te6edf3completeTb4b4b4(Tff7b72falseTb4b4b4)
Te6edf3queueResponseTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72fun Td2a8ffhandleQueueStatusTb4b4b4(Te6edf3queueStatusTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3QueueStatusTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffqueueStatus Tffd700${Te6edf3queueStatusTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Tb4b4b4(Te6edf3successTb4b4b4, Te6edf3isFullTb4b4b4, Te6edf3requestIdTb4b4b4) Tff7b72= Te6edf3withTb4b4b4(Te6edf3queueStatusTb4b4b4) Tb4b4b4{ Te6edf3TripleTb4b4b4(Te6edf3res Tff7b72=Tff7b72= T79c0ff0Tb4b4b4, Te6edf3free Tff7b72=Tff7b72= T79c0ff0Tb4b4b4, Te6edf3meshPacketIdTb4b4b4) Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3success Tff7b72&Tff7b72& Te6edf3isFullTb4b4b4) Tff7b72return T8b949e// Queue is full, wait for free != 0
Tff7b72if Tb4b4b4(Te6edf3requestId Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3queueResponseTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3requestIdTb4b4b4)Tff7b72?.Te6edf3completeTb4b4b4(Te6edf3successTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3queueResponseTb4b4b4.Te6edf3entriesTb4b4b4.Te6edf3lastOrNull Tb4b4b4{ Tff7b72!Tffa657itTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3isDone Tb4b4b4}Tff7b72?.Te6edf3valueTff7b72?.Te6edf3completeTb4b4b4(Te6edf3successTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72fun Td2a8ffremoveResponseTb4b4b4(Te6edf3dataRequestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3completeTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3queueResponseTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3dataRequestIdTb4b4b4)Tff7b72?.Te6edf3completeTb4b4b4(Te6edf3completeTb4b4b4)
Tb4b4b4}

Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffSwallowedExceptionTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffstartPacketQueueTb4b4b4(Te6edf3getConnectionStateTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Te6edf3ConnectionStateTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3queueJobTff7b72?.Te6edf3isActive Tff7b72=Tff7b72= Tff7b72trueTb4b4b4) Tff7b72return
Te6edf3queueJob Tff7b72=
Te6edf3scopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffpacket queueJob startedTa5d6ff"Tb4b4b4)
Tff7b72while Tb4b4b4(Te6edf3getConnectionStateTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3CONNECTEDTb4b4b4) Tb4b4b4{
T8b949e// take the first packet from the queue head
Tff7b72val Te6edf3packet Tff7b72= Te6edf3queuedPacketsTb4b4b4.Te6edf3pollTb4b4b4(Tb4b4b4) Tff7b72?: Tff7b72break
Tff7b72try Tb4b4b4{
T8b949e// send packet to the radio and wait for response
Tff7b72val Te6edf3response Tff7b72= Te6edf3sendPacketTb4b4b4(Te6edf3packetTb4b4b4, Te6edf3getConnectionStateTb4b4b4)
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffqueueJob packet id=Tffd700${Te6edf3packetTb4b4b4.Te6edf3idTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff waitingTa5d6ff"Tb4b4b4)
Tff7b72val Te6edf3success Tff7b72= Te6edf3responseTb4b4b4.Te6edf3getTb4b4b4(T79c0ff2Tb4b4b4, Te6edf3TimeUnitTb4b4b4.Te6edf3MINUTESTb4b4b4)
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffqueueJob packet id=Tffd700${Te6edf3packetTb4b4b4.Te6edf3idTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff success Tffd700$Te6edf3successTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3TimeoutExceptionTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffqueueJob packet id=Tffd700${Te6edf3packetTb4b4b4.Te6edf3idTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff timeoutTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffqueueJob packet id=Tffd700${Te6edf3packetTb4b4b4.Te6edf3idTb4b4b4.Te6edf3toUIntTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff failedTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e/** Change the status on a DataPacket and update watchers */
Tff7b72private Tff7b72fun Td2a8ffchangeStatusTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3mTb4b4b4: Te6edf3MessageStatusTb4b4b4) Tff7b72= Te6edf3scopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3packetId Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3getDataPacketByIdTb4b4b4(Te6edf3packetIdTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3p Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3status Tff7b72=Tff7b72= Te6edf3mTb4b4b4) Tff7b72returnTf0883e@handledLaunch
Te6edf3packetRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3updateMessageStatusTb4b4b4(Te6edf3pTb4b4b4, Te6edf3mTb4b4b4)
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastMessageStatusTb4b4b4(Te6edf3packetIdTb4b4b4, Te6edf3mTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffMagicNumberTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffgetDataPacketByIdTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3DataPacket? Tff7b72= Te6edf3withTimeoutOrNullTb4b4b4(T79c0ff1T79c0ff0T79c0ff0T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3dataPacketTb4b4b4: Te6edf3DataPacket? Tff7b72= Tff7b72null
Tff7b72while Tb4b4b4(Te6edf3dataPacket Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3dataPacket Tff7b72= Te6edf3packetRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3getPacketByIdTb4b4b4(Te6edf3packetIdTb4b4b4)Tff7b72?.Te6edf3data
Tff7b72if Tb4b4b4(Te6edf3dataPacket Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Te6edf3delayTb4b4b4(T79c0ff1T79c0ff0T79c0ff0Tb4b4b4)
Tb4b4b4}
Te6edf3dataPacket
Tb4b4b4}

Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffsendPacketTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4, Te6edf3getConnectionStateTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Te6edf3ConnectionStateTb4b4b4)Tb4b4b4: Te6edf3CompletableFutureTff7b72<Tffa657BooleanTff7b72> Tb4b4b4{
T8b949e// send the packet to the radio and return a CompletableFuture that will be completed with
T8b949e// the result
Tff7b72val Te6edf3future Tff7b72= Te6edf3CompletableFutureTff7b72<Tffa657BooleanTff7b72>Tb4b4b4(Tb4b4b4)
Te6edf3queueResponseTff7b72[Te6edf3packetTb4b4b4.Te6edf3idTff7b72] Tff7b72= Te6edf3future
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3getConnectionStateTb4b4b4(Tb4b4b4) Tff7b72!Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3CONNECTEDTb4b4b4) Tff7b72throw Te6edf3RadioNotConnectedExceptionTb4b4b4(Tb4b4b4)
Te6edf3sendToRadioTb4b4b4(Te6edf3ToRadioTb4b4b4.Te6edf3newBuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3packet Tff7b72= Te6edf3packet Tb4b4b4}Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffsendToRadio error:Ta5d6ff"Tb4b4b4, Te6edf3exTb4b4b4)
Te6edf3futureTb4b4b4.Te6edf3completeTb4b4b4(Tff7b72falseTb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3future
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffinsertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4: Te6edf3MeshLogTb4b4b4) Tb4b4b4{
Te6edf3scopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
T8b949e// Do not log, because might contain PII
T8b949e// info("insert: ${packetToSave.message_type} =
T8b949e// ${packetToSave.raw_message.toOneLineString()}")
Te6edf3meshLogRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3insertTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.29s